/*	Sample program for Olimex AVR-CAN with AT90CAN128 processor
 *	Echoes back the received characters on the USART0.
 *	Compile with AVRStudio+WinAVR (gcc version 3.4.6)
 */

#define	__AVR_AT90CAN128__	1
#define OSCSPEED	16000000		/* in Hz */

#include "avr/io.h"

void PORT_Init()
{
	PORTA = 0b00000000;
	DDRA = 0b00000000;

	PORTB = 0b00000000;
	DDRB = 0b00000000;

	PORTC = 0b00000000;
	DDRC = 0b00000000;

	PORTD = 0b00000000;
	DDRD = 0b00000000;

	PORTE = 0b00010000;		//Turn Led off (Bit4 = 1)
	DDRE = 0b00010010;		//Led set as output (Bit4 = 1), TX set as output (Bit1 = 1)

	PORTF = 0b00000000;
	DDRF = 0b00000000;
}

void WDT_Off(void)
{
	asm("push r30");	// using GCC without optimizations results in
	asm("ldi r30, 0x18");	// a code not meeting the requirements
	asm("sts 0x60, r30");	// of the datasheet.
	asm("ldi r30, 0x7");
	asm("sts 0x60, r30");
	asm("pop r30");
	WDTCR = (1<<WDCE) | (1<<WDE);
	WDTCR = 0x07;					//increase Watchdog time-out period (Bit0,1,2 = 1)
}

void UART_Init(uint32_t Baud)
{
	unsigned int BaudRate = OSCSPEED / (16 * Baud) - 1;	//calculate BaudRate
	//set BaudRate into registers
	UBRR0H = (unsigned char) (BaudRate>>8);
	UBRR0L = (unsigned char) BaudRate;

	UCSR0B = 0b00011000;		//enable TX(Bit4 = 1), RX(Bit3 = 1)

	UCSR0C = 0b00000110;		//set frame format (8 bits, 1 stop bit)
}

unsigned char UART_Receive()
{
	if (UCSR0A & 0b10000000)
		return UDR0;
	else
		return 0;
}

void UART_Transmit(unsigned char Data)
{
	while (!(UCSR0A & 0b00100000));
	UDR0 = Data;
}

int main()
{
	unsigned char Ch;
	WDT_Off();
	PORT_Init();
	UART_Init(9600);
	while (1)
	{
		asm("WDR");				//avoiding reset of the program
		Ch = UART_Receive();	//receiving char
		if (Ch)
		{
			UART_Transmit(Ch);	//returning char
		}
	}

}
